"""
字符串可以很容易地写入文件或从文件中读取。
数字则更麻烦一些，因为 read() 方法只返回字符串，而字符串必须传给 int() 这样的函数，它接受 '123' 这样的字符串并返回其数值 123。
当你想要保存嵌套列表和字典等更复杂的数据类型时，手动执行解析和序列化操作将会变得非常复杂。

Python 允许你使用流行的数据交换格式 JSON (JavaScript Object Notation)，而不是让用户持续编写和调试代码来将复杂的数据类型存入文件中。
标准库模块 json 可以接受带有层级结构的 Python 数据，并将其转换为字符串表示形式；这个过程称为 serializing。 根据字符串表示形式重建数据则称为 deserializing。
在序列化和反序列化之间，用于代表对象的字符串可以存储在文件或数据库中，或者通过网络连接发送到远端主机。
### 使用 JSON 保存结构化数据

JSON（JavaScript Object Notation）是一种轻量级的数据交换格式，广泛用于现代应用程序中。Python 提供了 `json` 模块，可以轻松地将复杂的数据结构（如列表、字典等）序列化为 JSON 字符串，并将其保存到文件或通过网络传输。

#### 1. **序列化数据**
   - **`json.dumps()`**：将 Python 对象转换为 JSON 格式的字符串。
     ```python
     import json
     data = [1, "simple", "list"]
     json_str = json.dumps(data)
     print(json_str)  # 输出: [1, "simple", "list"]
     ```
   - **`json.dump()`**：将 Python 对象直接写入文件。
     ```python
     with open('data.json', 'w', encoding='utf-8') as f:
         json.dump(data, f)
     ```

#### 2. **反序列化数据**
   - **`json.loads()`**：从 JSON 字符串中解析出 Python 对象。
     ```python
     loaded_data = json.loads(json_str)
     print(loaded_data)  # 输出: [1, 'simple', 'list']
     ```
   - **`json.load()`**：从文件中读取并解析 JSON 数据。
     ```python
     with open('data.json', 'r', encoding='utf-8') as f:
         loaded_data = json.load(f)
     print(loaded_data)  # 输出: [1, 'simple', 'list']
     ```

#### 3. **注意事项**
   - **编码问题**：JSON 文件必须以 UTF-8 编码存储和读取，确保在打开文件时指定 `encoding="utf-8"`。
   - **数据类型支持**：
     - `json` 模块原生支持基本数据类型（如整数、浮点数、字符串、布尔值、列表、字典等）。
     - 对于自定义类的实例，需要额外处理（例如使用 `default` 参数或继承 `json.JSONEncoder` 类）。
   - **安全性**：`json` 是安全的，适用于处理来自不可信来源的数据，因为它不会执行代码。

#### 4. **与其他模块对比**
   - **`pickle` 模块**：
     - `pickle` 是 Python 特有的序列化协议，能够处理几乎所有 Python 对象（包括自定义类的实例）。
     - 但它是不安全的，因为解序化的数据可能包含恶意代码，因此不应用于处理不可信来源的数据。
     - 示例：
       ```python
       import pickle
       # 序列化
       with open('data.pkl', 'wb') as f:
           pickle.dump(data, f)
       # 反序列化
       with open('data.pkl', 'rb') as f:
           loaded_data = pickle.load(f)
       ```

#### 5. **最佳实践**
   - **避免使用 `from module import *`**：这会导致命名空间污染，增加冲突的风险。
   - **合理组织代码**：对于复杂的项目，建议将不同的功能模块化，便于管理和维护。
   - **优化编译模块大小**：可以使用 `-O` 或 `-OO` 开关来减小编译后的模块大小，但这可能会影响程序的行为，需谨慎使用。

### 总结
- **JSON 的优势**：JSON 是一种通用的数据交换格式，易于阅读和编写，适合跨语言的数据传输。
- **Python 的支持**：Python 提供了强大的 `json` 模块，简化了数据的序列化和反序列化过程。
- **适用场景**：适合保存简单的数据结构（如列表、字典），以及与其他系统进行数据交互。
"""
import json

# 基本术语：序列化（Serialization）	把 Python 对象转换为 JSON 字符串（便于传输或存储）
# 反序列化（Deserialization）	把 JSON 字符串转换为 Python 对象（便于程序使用


# JSON 的基本类型映射
# Python 类型	JSON 类型
# dict	object
# list, tuple	array
# str	string
# int, float	number
# True	true
# False	false
# None	null

# 序列化：将 Python 对象转成 JSON 字符串   （json.dumps(obj, indent=2, ensure_ascii=False, ...)）

data ={
    "name": "John",
    "age": 30,
    "city": "New York",
    "hobbies": ["reading", "swimming", "coding"],
    "is_married": True,
    "address": {
        "street": "123 Main St",
        "city": "New York",
        "state": "NY",
        "zip": "10001"
    }
}
data_string = json.dumps(data, indent=2, ensure_ascii=False)
print(data_string)
print(type(data_string))
print(json.loads(data_string))

# 反序列化：将 JSON 字符串转成 Python 对象   （json.loads(json_string)）

json_string = '{"name": "John", "age": 30, "city": "New York", "hobbies": ["reading", "swimming", "coding"], "is_married": true, "address": {"street": "123 Main St", "city": "New York", "state": "NY", "zip": "10001"}}'

data_dict = json.loads(json_string)
print(data_dict)
print(type(data_dict))

# 将 Python 对象写入文件（保存为 JSON）

with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=2, ensure_ascii=False)


# 从文件读取 JSON 并解析为 Python 对象
with open("data.json", "r", encoding="utf-8") as f:
    loaded_data = json.load(f)

print(loaded_data["age"])



# 自定义对象的序列化与反序列化默认情况下，json 模块不支持自定义类的对象。需要我们自己实现序列化逻辑。

class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 自定义 JSON 编码器（继承 json.JSONEncoder）

class UserEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, User):
            return {"name": obj.name, "age": obj.age}
        return super().default(obj)
#  使用自定义编码器序列化对象
user = User("Charlie", 28)
json_user = json.dumps(user, cls=UserEncoder, indent=2, ensure_ascii=False)
print(json_user)

#
# 函数名	输入类型	输出类型	用途说明
# json.dumps()	Python 对象	JSON 字符串	把 Python 对象 转为字符串形式的 JSON
# json.dump()	Python 对象 + 文件	写入文件中	把 Python 对象 保存到 JSON 文件中
# json.loads()	JSON 字符串	Python 对象	把 JSON 字符串 解析为 Python 对象
# json.load()	JSON 文件	Python 对象	从 JSON 文件中 读取并解析为 Python 对象












